package cheme.ProcessModel.ProcessUnits.Streams.Tags;

import java.beans.PropertyChangeEvent;
import java.util.Iterator;
import java.util.List;

import cheme.ProcessModel.ChemePropertyChangeEvent;
import cheme.ProcessModel.IInterpretable;
import cheme.ProcessModel.IModelElement;
import cheme.ProcessModel.IPropertyAware;
import cheme.ProcessModel.IXmlOperations;
import cheme.ProcessModel.Table.Field;
import cheme.ProcessModel.Table.Row;
import cheme.ProcessModel.Visitors.IVisitor;
import cheme.ProcessModel.IXmlOperations;

public abstract class AbstractTagComponent extends Row implements ITagComponent, IInterpretable, IXmlOperations
{
	/*
	 * Serialization version identifier. (Set to default for now)
	 */
	
	private static final long serialVersionUID = 1L;
	
	/*
	 * When initializing is set to true edits will not change the isInitial state of this component.
	 * Useful for non-constructor initialization operations.
	 */
	
	protected boolean initializing = true;

	public static final String DEFAULT_VALUE = "";
	public static final String DEFAULT_QTY_VALUE = "?";//PA Change
	
	public AbstractTagComponent(IModelElement parent)
	{
		super(parent);
		initializing = true;
		defaultInit();
	}
	
	protected void defaultInit()
	{
		LabelField label = new LabelField(this, DEFAULT_VALUE);
		label.setToolTipText("The name used to refer to this stream component in your chemical process.\n" +
								"You can build equations involving this stream component by dragging and dropping this label into the equations editor.");
		add(label, LABEL_INDEX);
		
		QuantityField quantity = new QuantityField(this, DEFAULT_QTY_VALUE);
		quantity.setToolTipText("The quantity for this stream component.");
		add(quantity, QUANTITY_INDEX);
		
//		UnitsField units = new UnitsField(this, 0);
//		units.setToolTipText("The unit of measurement for this stream component.");
//		add(units, UNITS_INDEX);
		
//		MaterialField material = new MaterialField(this, 0);
//		material.setToolTipText("The material of this stream component.");
//		add(material, MATERIAL_INDEX);
	}
	
	public void initialize(ITagComponentInitPolicy initPolicy)
	{
		if(null != initPolicy)
		{
			//apply the init
			initPolicy.init(this);
		}
		
		// mark as init
		setInitial(true);
		
		initializing = false;
	}
	
	protected void setInitial(boolean initial)
	{
		/*
		 * Only update this initial state and fire an event if initialization is complete.
		 */
		if(false == initializing)
		{
			isInitial = initial;
			firePropertyChange(P_INITIAL, null, initial);
		}
	}
	
	public boolean isInitial()
	{
		return isInitial;
	}
	
	public boolean hasUnknownValue()
	{
		/*
		 * Cannot be an unkown value if it is an initial dummy component... ?
		 */
		String quantity = getQuantity().trim();
		boolean bstatus = false;
		if (quantity.equals("?") || quantity.isEmpty())
		{
			bstatus = true;
		}
		return !isInitial() && bstatus;
		//return !isInitial() && (quantity.equals("?") || quantity.isEmpty());
	}
	
	/**
	 * @return the label
	 */
	public String getLabel()
	{
		return get(LABEL_INDEX).getText();
	}
	
	/**
	 * @param label the label to set
	 */
	public void setLabel(String label)
	{
		set(LABEL_INDEX, label.trim(), IPropertyAware.P_LABEL);
	}
	
	/**
	 * @return the quantity
	 */
	public String getQuantity()
	{
		return get(QUANTITY_INDEX).getText();
	}
	
	/**
	 * @param quantity the quantity to set
	 */
	public void setQuantity(String quantity)
	{
		set(QUANTITY_INDEX, quantity.trim(), IPropertyAware.P_QUANTITY);
	}
	
	/**
	 * @return the units
	 */
	public String getUnits()
	{
		return get(UNITS_INDEX).getText();
	}
	
	/**
	 * @param units the units to set
	 */
	public void setUnits(String units)
	{
		set(UNITS_INDEX, units.trim(), IPropertyAware.P_UNITS);
	}

	//PA Change
	public String getMaterial()
	{
		return get(MATERIAL_INDEX).getText();
	}
	
	@Override
	protected void setInternal(int index, Field value)
	{
		get(index).set(value);
	}
	
	/*
	 * Note that this method is responding to children changes in their content and transforming them
	 * into interpretable events.
	 */
	@Override
	public void propertyChange(PropertyChangeEvent evt)
	{		
		boolean fireInterpretEvt = (!initializing && 
				(evt.getPropertyName().equals(IPropertyAware.P_LABEL) ||
				evt.getPropertyName().equals(IPropertyAware.P_QUANTITY) ||
				evt.getPropertyName().equals(IPropertyAware.P_UNITS)) ||
				evt.getPropertyName().equals(IPropertyAware.P_MATERIAL));
		
		if(true == fireInterpretEvt)
		{
			setInitial(false);
			
			super.firePropertyChange(
					new ChemePropertyChangeEvent(this, P_INTERPRETABLE, null, this, evt));
		}
	}
	
	public Object fromXml() {
		// TODO Auto-generated method stub
		return null;
	}

	public String toXml() {
		
		//list of children
		List<Field> children = this.getChildren();
		Iterator i = children.iterator();
		
		String xml = "";
		xml += "<TagComponent type=\"generic\">";
		xml += "<Components>";
		while(i.hasNext())
		{
			xml+= ((IXmlOperations)i.next()).toXml();
		}
		xml += "</Components>";
		xml += "</TagComponent>";
		return xml;
	}
	
//	@Override
//	protected void handleTextChange(PropertyChangeEvent evt)
//	{
//		if(!initializing)
//		{
//			setInitial(false);
//			firePropertyChange(
//					new ChemePropertyChangeEvent(this, P_TEXT, null, this, evt));
//		}
//	}
}
